<script lang="ts">
  import type { KeyValuePair } from "@sparrow/common/interfaces/request.interface";
  import { TabularInputTheme } from "../../utils";
  import { afterUpdate, onMount } from "svelte";
  import { Tooltip, Button, notifications } from "@sparrow/library/ui";
  import { Checkbox } from "@sparrow/library/forms";
  import {
    ErrorInfoIcon,
    Information,
    CheckMarkIcon,
    ArrowUndoRegular,
    ArrowUpFilled,
    ArrowDownRegular,
  } from "@sparrow/library/icons";
  import BulkEditEditor from "./sub-component/BulkEditEditor.svelte";
  import LazyElement from "./LazyElement.svelte";
  import { Toggle } from "@sparrow/library/ui";
  import {
    handleEventOnClickApplyUndoAI,
    handleEventonClickApplyChangesAI,
  } from "@sparrow/common/utils";

  export let environmentVariables;
  export let handleOpenCurrentDynamicExpression;

  export let onUpdateEnvironment;
  export let onToggleBulkEdit;
  export let isBulkEditActive = false;
  export let isBulkEditRequired = false;
  export let isBulkEditHeaderInfoRequired = false;
  export let isCheckBoxEditable = true;
  export let isTopHeaderRequired = true;
  export let isInputBoxEditable = true;
  export let bulkEditPlaceholder = "";
  export let dynamicExpression = false;
  // export let type: "file" | "text" = "text";

  // exports
  export let keyValue: KeyValuePair[];
  export let callback: (pairs: KeyValuePair[]) => void;
  export let readable: { key: string; value: string } = {
    key: "",
    value: "",
  };

  // New props for merge/diff view **anish
  export let showMergeView = false;
  export let isMergeViewLoading = false;
  export let newModifiedPairs: KeyValuePair[] = [];

  let hasChanges = false;
  let enableKeyValueHighlighting = true;
  let pairs: KeyValuePair[] = keyValue;
  let controller: boolean = false;

  // New variables for diff navigation
  let changedPairIndices: number[] = [];
  let currentChangeIndex = 0;
  let totalChanges = 0;

  let bulkText = "";
  let diffBulkText = ""; // contains new modified content for comparision for bulk editor
  let bulkToggle = isBulkEditActive;

  let isErrorIconHovered = false;
  let isAutoGeneratedInfoHovered = false;

  let isValidSyntax = true;
  let pairsContainer: HTMLElement;

  // This is a flag to determine if we should scroll to the bottom
  let shouldScrollToBottom = false;

  // This is for scrolling into view when a new row is added and the component updates
  afterUpdate(() => {
    if (shouldScrollToBottom && pairsContainer) {
      const lastRow = pairsContainer.lastElementChild;
      if (lastRow) {
        lastRow.scrollIntoView({ behavior: "auto", block: "end" });
      }
      shouldScrollToBottom = false;
    }
  });

  const theme = new TabularInputTheme().build();

  // ********** Diff/Merge View Methods - Start **********

  // Calculate diff between original and current data **anish
  type DiffType = "added" | "deleted" | "modified" | "unchanged";
  type DiffPair = KeyValuePair & {
    diffType: DiffType;
    originalIndex?: number;
    currentIndex?: number;
  };
  let diffPairs: DiffPair[] = []; // contains new modified content for comparision for TabularInput

  // Funtion to calculate diff. b/w origional data (pairs) and new data (newModifiedPairs)
  function calculateDiff(): DiffPair[] {
    // If table data is empty but we have new data, then consider everything as an addition
    // if (!pairs || pairs.length === 0) {
    //   return newModifiedPairs.map((pair) => ({
    //     ...pair,
    //     diffType: "added",
    //     currentIndex: newModifiedPairs.indexOf(pair),
    //   }));
    // }

    const result: DiffPair[] = [];
    const origMap = new Map();

    // Create a map of original items using key as a unique identifier
    pairs.forEach((pair, index) => {
      origMap.set(pair.key, { pair, index });
    });
    // Check for modified or added items
    newModifiedPairs.forEach((currentPair, currentIndex) => {
      if (currentPair.key === "") return; // Skip empty rows

      const originalEntry = origMap.get(currentPair.key);

      if (originalEntry) {
        // Key exists in both - check if value changed
        if (originalEntry.pair.value !== currentPair.value) {
          result.push({
            ...currentPair,
            diffType: "modified",
            originalIndex: originalEntry.index,
            currentIndex,
          });

          // Also add the original version to show what changed
          result.push({
            ...originalEntry.pair,
            diffType: "deleted",
            originalIndex: originalEntry.index,
          });
        } else {
          // Unchanged
          result.push({
            ...currentPair,
            diffType: "unchanged",
            originalIndex: originalEntry.index,
            currentIndex,
          });
        }

        // Mark as processed
        origMap.delete(currentPair.key);
      } else {
        // New item
        result.push({
          ...currentPair,
          diffType: "added",
          currentIndex,
        });
      }
    });

    // Add deleted items (those in original but not in current)
    origMap.forEach(({ pair, index }) => {
      if (pair.key !== "") {
        // Skip empty rows
        result.push({
          ...pair,
          diffType: "deleted",
          originalIndex: index,
        });
      }
    });

    // Comparator: Custom sorting method for sorting by original position to maintain a logical order
    result.sort((a, b) => {
      // First priority: Group items with the same key together
      if (a.key === b.key) {
        // When keys match, deleted comes before added
        if (
          a.diffType === "deleted" &&
          (b.diffType === "added" || b.diffType === "modified")
        ) {
          return -1; // Deletion comes first
        }
        if (
          (a.diffType === "added" || a.diffType === "modified") &&
          b.diffType === "deleted"
        ) {
          return 1; // Addition comes second
        }
      }

      // Second priority: Put completely new items at the end
      const aIsNew = a.diffType === "added" && a.originalIndex === undefined;
      const bIsNew = b.diffType === "added" && b.originalIndex === undefined;

      if (aIsNew && !bIsNew) {
        return 1; // a is new but b is not - push a to the end
      } else if (!aIsNew && bIsNew) {
        return -1; // b is new but a is not - push b to the end
      }

      // Then sort by original position for existing items
      if (a.originalIndex !== undefined && b.originalIndex !== undefined) {
        return a.originalIndex - b.originalIndex;
      }

      // Fall back to current position
      if (a.currentIndex !== undefined && b.currentIndex !== undefined) {
        return a.currentIndex - b.currentIndex;
      }

      return 0;
    });

    const lastEmptyRow: DiffPair = {
      key: "",
      value: "",
      checked: false,
      diffType: "unchanged",
      originalIndex: result.length - 1,
      currentIndex: result.length - 1,
    };

    return [...result, lastEmptyRow];
  }

  /**
   * Checks if there are any actual changes between the original data and the new data
   * Sets hasChanges to true if there are added, deleted, or modified items
   */
  function checkForChanges(): boolean {
    if (!diffPairs || diffPairs.length === 0) return false;

    // Check if there are any changes (added, deleted, or modified items)
    const changes = diffPairs.filter(
      (pair) =>
        pair.diffType === "added" ||
        pair.diffType === "deleted" ||
        pair.diffType === "modified",
    );

    // Update hasChanges state
    hasChanges = changes.length > 0;

    updateChangedIndices(); // Update changed indices for navigation

    if (!hasChanges) {
      undoChanges(); // resetting the mergeview states and props
      notifications.success("You already have updated changes.");
    }

    return hasChanges;
  }

  // Convert diffPairs to bulk text format for BulkEditEditor
  function diffPairsToBulkText(): string {
    if (!diffPairs || !diffPairs.length) return "";

    return diffPairs
      .filter((pair) => pair.diffType !== "deleted" && (pair.key || pair.value))
      .map((pair) => `${pair.key}:${pair.value}`)
      .join("\n");
  }

  // Convert pairs to bulk text format
  function pairsToBulkText(pairsToConvert: KeyValuePair[]): string {
    return pairsToConvert
      .filter((pair) => pair.key || pair.value)
      .map((pair) => `${pair.key}:${pair.value}`)
      .join("\n");
  }

  const updateDiffPairsWithLoading = async () => {
    isMergeViewLoading = true;
    await sleep(2000);
    diffPairs = calculateDiff();
    diffBulkText = diffPairsToBulkText();
    checkForChanges();
    isMergeViewLoading = false;

    // If there are changes, scroll to the first one automatically
    if (totalChanges > 0) {
      currentChangeIndex = 0;

      setTimeout(() => {
        scrollToChange(changedPairIndices[0]);
      }, 200);
    }
  };
  $: if (showMergeView) updateDiffPairsWithLoading();

  // Toggle merge view **anish
  const toggleMergeView = async (show: boolean) => {
    showMergeView = show;
    if (show) {
      isMergeViewLoading = true;
      await sleep(2000);
      diffPairs = calculateDiff();
      checkForChanges();

      // Update bulk text to reflect diff if bulk edit is active
      if (isBulkEditActive) {
        bulkText = diffPairsToBulkText();
      }
    } else hasChanges = false; // Reset when merge view is disabled
  };

  // Function to apply all changes from diff view to the original data
  const applyChanges = async () => {
    if (!showMergeView) return;
    isMergeViewLoading = true;
    // Extract all valid pairs from diffPairs (excluding deleted ones)
    const updatedPairs = diffPairs
      .filter((pair) => pair.diffType !== "deleted")
      .map((pair) => ({
        key: pair.key,
        value: pair.value,
        checked: pair.checked || false,
      }));

    // Add an empty row at the end if needed
    if (
      updatedPairs.length > 0 &&
      (updatedPairs[updatedPairs.length - 1].key !== "" ||
        updatedPairs[updatedPairs.length - 1].value !== "")
    ) {
      updatedPairs.push({ key: "", value: "", checked: false });
    }

    pairs = updatedPairs; // Update the pairs array with the new data
    showMergeView = false; // Turn off merge view after applying changes
    callback(pairs); // Notify parent component of the changes
    // newModifiedPairs = JSON.parse(JSON.stringify(pairs)); // Save current state for potential future comparison
    newModifiedPairs = [];
    hasChanges = false; // Reset after applying changes

    currentChangeIndex = 0;
    totalChanges = 0;

    await sleep(2000);
    isMergeViewLoading = false; // Reset loading state
    handleEventonClickApplyChangesAI("TabularInput", "headers && parameters");
  };

  // Function to undo all changes and revert to original state
  const undoChanges = async () => {
    if (!showMergeView) return;
    showMergeView = false;
    newModifiedPairs = [];
    diffPairs = []; // Reset any potential changes by discarding diffPairs
    callback(pairs); // Notify parent of unchanged data
    hasChanges = false; // Reset hasChanges after undoing changes

    currentChangeIndex = 0;
    totalChanges = 0;

    isMergeViewLoading = true;
    await sleep(2000);
    isMergeViewLoading = false; // Reset loading state
    handleEventOnClickApplyUndoAI("TabularInput", "headers && parameters");
  };

  // Utility function to create a delay
  const sleep = (ms: number): Promise<void> => {
    return new Promise((resolve) => setTimeout(resolve, ms));
  };

  // ********** Diff/Merge View Methods - End **********

  onMount(() => {
    handleBulkTextUpdate();

    if (showMergeView) {
      diffPairs = calculateDiff();
      diffBulkText = diffPairsToBulkText();
      checkForChanges();
    }
  });

  // Update diff when inputs change
  $: {
    if (keyValue) {
      identifySelectAllState();
    }
  }

  /**
   * @description - calculates the select all checkbox state - weather checked or not
   */
  const identifySelectAllState = () => {
    pairs = [];
    pairs = keyValue;
    controller = false;
    if (pairs.length > 1) {
      let isUncheckedExist: boolean = false;
      for (let i = 0; i < pairs.length - 1; i++) {
        if (pairs[i].checked === false) {
          isUncheckedExist = true;
          break;
        }
      }
      if (isUncheckedExist) {
        controller = false;
      } else {
        controller = true;
      }
    }
  };

  const updateParam = async (index: number): Promise<void> => {
    pairs = pairs;
    if (
      pairs.length - 1 === index &&
      // although in readonly mode input is disabled
      // but codemirror internally invokes this function and updates key value
      // so one more extra check here for read only mode
      isInputBoxEditable &&
      (pairs[index].key !== "" || pairs[index].value !== "")
    ) {
      pairs[pairs.length - 1].checked = true;
      pairs.push({ key: "", value: "", checked: false });
      shouldScrollToBottom = true;
      pairs = pairs;
      callback(pairs);

      // Recalculate diff if merge view is active (althrough will disable the edit while in merge view) **anish
      if (showMergeView) {
        diffPairs = calculateDiff();
        diffBulkText = diffPairsToBulkText(); // ToDo: Calculate only if Bulk Edit mode is active (change in every place)
        checkForChanges();
      }
    } else {
      callback(pairs);
    }
  };

  let isBulkEditLoaded = false;

  /**
   * Updates the bulk text based on the key-value pairs.
   */
  const handleBulkTextUpdate = () => {
    // Define the syntax validation regex pattern (key:value)
    const syntaxPattern = /^[^:]+:.+$/;

    // Map each pair to a formatted line (key:value), validate syntax, and filter out invalid lines
    const res = pairs
      .map((elem) => {
        // Create a line from key and value, or empty string if both are empty
        const line = elem.key || elem.value ? `${elem.key}:${elem.value}` : "";

        // Validate syntax for each non-empty line
        if (line && !syntaxPattern.test(line)) {
          isValidSyntax = false;
        }

        return line;
      })
      .filter((item) => item) // Filter out empty lines
      .join("\n"); // Join lines with newline characters

    // Update the bulkText with the formatted and validated text
    bulkText = res;
    isBulkEditLoaded = true;
  };

  const handleBulkTextarea = (event) => {
    bulkText = event.detail;

    // remove all empty lines
    const res = bulkText.split("\n").filter((line) => line.trim() !== "");

    // Pushing a blank string to add a blank key value at the end
    res.push("");

    // Define the syntax validation regex pattern (key:value)
    const syntaxPattern = /^[^:]+:.+$/;

    // Initialize isValidSyntax to true
    isValidSyntax = true;

    const newPairs = res.map((elem) => {
      if (elem.length) {
        const firstColonIndex = elem.indexOf(":");
        let key, value;

        if (firstColonIndex !== -1) {
          key = elem.substring(0, firstColonIndex).trim();
          value = elem.substring(firstColonIndex + 1).trim();
        } else {
          key = elem.trim();
          value = "";
        }

        // Validate syntax for each non-empty line
        if (elem && !syntaxPattern.test(elem)) {
          isValidSyntax = false;
        }

        return {
          key: key,
          value: value,
          checked: true,
        };
      } else {
        return {
          key: "",
          value: "",
          checked: false,
        };
      }
    });

    // If in merge view mode, update the newModifiedPairs
    if (showMergeView) {
      diffPairs = calculateDiff();
      diffBulkText = diffPairsToBulkText();
      checkForChanges();
    } else {
      pairs = newPairs;
      callback(pairs);
    }
  };

  const toggleBulkEdit = (event) => {
    onToggleBulkEdit(event.target.checked);

    // Update bulk text if toggling to bulk edit mode
    if (event.target.checked) {
      handleBulkTextUpdate();
      diffBulkText = diffPairsToBulkText();
    } else {
      if (showMergeView) {
        setTimeout(() => {
          scrollToChange(changedPairIndices[currentChangeIndex]);
        }, 30);
      }
    }
  };

  const deleteParam = (index: number): void => {
    if (pairs.length > 1) {
      let filteredKeyValue = pairs.filter((elem, i) => {
        if (i !== index) {
          return true;
        }
        return false;
      });
      pairs = filteredKeyValue;
    }
    callback(pairs);
    setTimeout(() => {
      pairs[pairs.length - 1].key = "";
      pairs[pairs.length - 1].value = "";
    }, 0);
  };

  const updateCheck = (index: number): void => {
    let filteredKeyValue = pairs.map((elem, i) => {
      if (i === index) {
        elem.checked = !elem.checked;
      }
      return elem;
    });
    pairs = filteredKeyValue;
    callback(pairs);
  };

  const handleCheckAll = (): void => {
    let flag: boolean;
    if (controller === true) {
      flag = false;
    } else {
      flag = true;
    }
    let filteredKeyValue = pairs.map((elem, i) => {
      if (i !== pairs.length - 1) {
        elem.checked = flag;
      } else if (!isInputBoxEditable) {
        elem.checked = flag;
      }
      return elem;
    });
    pairs = filteredKeyValue;
    callback(pairs);
  };

  const handleErrorHover = () => {
    isErrorIconHovered = !isErrorIconHovered;
  };

  const handleAutoGeneratedInfoHover = () => {
    isAutoGeneratedInfoHovered = !isAutoGeneratedInfoHovered;
  };

  // ********** Diff/Merge Navigate & Accept per Line - Start ********
  /**
   * Update indices of changed rows for navigation
   */
  function updateChangedIndices(): void {
    changedPairIndices = [];

    for (let i = 0; i < diffPairs.length; i++) {
      if (
        diffPairs[i].diffType === "deleted" &&
        diffPairs[i + 1] &&
        diffPairs[i + 1].diffType === "modified"
      ) {
        changedPairIndices.push(i);
        i += 1; // Skip the next one as it's part of the same group
      } else if (
        diffPairs[i].diffType === "added" ||
        diffPairs[i].diffType === "deleted"
      ) {
        changedPairIndices.push(i);
      }
    }

    totalChanges = changedPairIndices.length; // Update total changes and reset current index if needed

    if (currentChangeIndex >= totalChanges) {
      currentChangeIndex = totalChanges > 0 ? 0 : -1;
    } else if (currentChangeIndex < 0 && totalChanges > 0) {
      currentChangeIndex = 0;
    }
  }

  /**
   * Navigates to the next change in the diff view
   */
  function goToNextChange(): void {
    if (totalChanges > 0) {
      currentChangeIndex = (currentChangeIndex + 1) % totalChanges;
      scrollToChange(changedPairIndices[currentChangeIndex]);
    }
  }

  /**
   * Navigates to the previous change in the diff view
   */
  function goToPreviousChange(): void {
    if (totalChanges > 0) {
      currentChangeIndex =
        (currentChangeIndex - 1 + totalChanges) % totalChanges;
      scrollToChange(changedPairIndices[currentChangeIndex]);
    }
  }

  /**
   * Scrolls to a specific row in the diff view
   */
  function scrollToChange(rowIndex: number): void {
    if (pairsContainer && rowIndex >= 0) {
      const rows = pairsContainer.querySelectorAll(".diff-row");

      if (rows && rows[rowIndex]) {
        // First, hide all diff-actions elements
        rows.forEach((row) => {
          // row.classList.remove("highlighted");

          // Find the next sibling that has the diff-actions class
          const diffActions = row.nextElementSibling?.classList.contains(
            "diff-actions",
          )
            ? row.nextElementSibling
            : null;

          // Hide all diff-actions
          if (diffActions) {
            diffActions.style.display = "none";
          }
        });

        rows[rowIndex].scrollIntoView({ behavior: "smooth", block: "center" });

        // Add the highlight class after a small delay to ensure scrolling has finished
        setTimeout(() => {
          // rows[rowIndex].classList.add("highlighted"); // Highlight the row

          // Show the diff-actions for the highlighted row if it exists
          const highlightedRowActions = rows[
            rowIndex
          ].nextElementSibling?.classList.contains("diff-actions")
            ? rows[rowIndex].nextElementSibling
            : null;

          if (highlightedRowActions) {
            highlightedRowActions.style.display = "flex";
          }
        }, 20);
      }
    }
  }

  /**
   * Accept a specific change (either added or modified)
   */
  const acceptChange = async (index: number) => {
    if (index < 0 || index >= diffPairs.length) return;

    const change = diffPairs[index];
    if (change.diffType === "added") {
      // For added rows, add to original pairs
      diffPairs[index].diffType = "unchanged";
      const newPair = {
        key: change.key,
        value: change.value,
        checked: change.checked || false,
      };

      // Add to pairs array (excluding the last empty row)
      pairs = [
        ...pairs.slice(0, -1),
        newPair,
        { key: "", value: "", checked: false },
      ];
    } else if (change.diffType === "deleted") {
      const nextModifiedRow = diffPairs[index + 1];
      if (nextModifiedRow && nextModifiedRow.diffType === "modified") {
        nextModifiedRow.diffType = "unchanged";

        // Update the corresponding pair in pairs array
        const pairIndex = pairs.findIndex((p) => p.key === change.key);
        if (pairIndex !== -1) {
          pairs[pairIndex] = {
            key: nextModifiedRow.key,
            value: nextModifiedRow.value,
            checked: nextModifiedRow.checked || false,
          };
          pairs = [...pairs]; // Trigger reactivity
        }
      }

      const deletedIndex = diffPairs.findIndex(
        (p) => p.diffType === "deleted" && p.key === change.key,
      );

      if (deletedIndex !== -1) {
        diffPairs.splice(deletedIndex, 1);
        diffPairs = [...diffPairs]; // Trigger reactivity
      }
    }

    // ToDo: Will remove these setTimeouts whiling pushing to production
    // setTimeout(() => {

    updateChangedIndices(); // Update navigation indices
    diffBulkText = diffPairsToBulkText(); // Update both diff bulk text and regular bulk text
    // bulkText = pairsToBulkText(pairs);

    callback(pairs); // Notify parent of changes

    // If no more changes, potentially disable merge view
    if (totalChanges === 0) {
      isMergeViewLoading = true;
      await sleep(2000);
      showMergeView = false;
      hasChanges = false;
      isMergeViewLoading = false;
    }
    // }, 200); // Reduced timeout for better responsiveness

    scrollToChange(changedPairIndices[0]);
  };

  /**
   * Reject a specific change
   */
  const rejectChange = async (index: number) => {
    if (index < 0 || index >= diffPairs.length) return;

    const change = diffPairs[index];
    if (change.diffType === "added") {
      diffPairs.splice(index, 1); // Remove the added entry from diffPairs
      diffPairs = [...diffPairs]; // Trigger reactivity
    } else if (change.diffType === "deleted") {
      change.diffType = "unchanged"; // Keep the original entry by marking it as unchanged

      // Find and remove the corresponding modified row if it exists
      const nextModifiedRow = diffPairs[index + 1];
      if (nextModifiedRow && nextModifiedRow.diffType === "modified") {
        const deletedIndex = diffPairs.findIndex(
          (p) => p.diffType === "modified" && p.key === change.key,
        );
        if (deletedIndex !== -1) {
          diffPairs.splice(deletedIndex, 1); // Remove the modified entry and keep the original

          // Ensure the original entry is reflected in pairs array
          const originalPair = {
            key: change.key,
            value: change.value,
            checked: change.checked || false,
          };

          const pairIndex = pairs.findIndex((p) => p.key === change.key);
          if (pairIndex !== -1) {
            pairs[pairIndex] = originalPair;
            pairs = [...pairs]; // Trigger reactivity
          }
        }
      }
      diffPairs = [...diffPairs]; // Trigger reactivity
    }

    // setTimeout(() => {

    updateChangedIndices(); // Update navigation indices
    diffBulkText = diffPairsToBulkText(); // Update both diff bulk text and regular bulk text
    // bulkText = pairsToBulkText(pairs);
    callback(pairs); // Notify parent of changes

    // If no more changes, potentially disable merge view
    if (totalChanges === 0) {
      isMergeViewLoading = true;
      await sleep(2000);
      showMergeView = false;
      hasChanges = false;
      isMergeViewLoading = false;
    }
    // }, 200); // Reduced timeout for better responsiveness

    scrollToChange(changedPairIndices[0]);
  };

  // ********** Diff/Merge Navigate & Accept per Line - End **********
</script>

<div>
  {#if !isBulkEditActive}
    <section class="mb-0 me-0 py-0 section-layout w-100" style="">
      <div
        class="d-flex align-items-center pair-header-row {!isTopHeaderRequired
          ? 'd-none'
          : ''}"
        style="position:relative; padding-right:1rem; padding-left:4px; border-top-left-radius: 4px; border-top-right-radius: 4px;"
      >
        <div style="width:50px; padding-left: 25px;" class="">
          <Checkbox
            size="small"
            disabled={pairs.length === 1 || !isCheckBoxEditable}
            checked={controller}
            on:input={handleCheckAll}
          />
        </div>

        <div
          class="d-flex gap-0"
          style="width: calc(100% - {dynamicExpression ? '220px' : '188px'});"
        >
          <div
            class="w-50 position-relative header-text"
            style="padding-left: 16px;"
          >
            Key
          </div>
          <div
            class="w-50 position-relative header-text"
            style="padding-left: 69px;"
          >
            Value
          </div>
        </div>
        <div style="width:140px;" class="ms-3 d-flex align-items-center">
          <div class="w-100 d-flex">
            <div class="w-100 d-flex justify-content-end gap-2">
              {#if isBulkEditRequired}
                <Toggle
                  bind:isActive={bulkToggle}
                  label="Bulk Edit"
                  fontSize="12px"
                  textColor="var(--text-ds-neutral-200)"
                  fontWeight="400"
                  onClick={handleBulkTextUpdate}
                  onChange={toggleBulkEdit}
                />
              {/if}
              <!-- <Toggle
                isActive={showMergeView}
                label="Show Diff"
                fontSize="12px"
                textColor="var(--text-ds-neutral-200)"
                fontWeight="400"
                onChange={() => toggleMergeView(!showMergeView)}
              /> -->
            </div>
          </div>
        </div>
      </div>
      <div
        class="w-100"
        style="display:block; position:relative;"
        bind:this={pairsContainer}
      >
        {#if readable.key || readable.value}
          <LazyElement
            element={{
              key: readable.key,
              value: readable.value,
              checked: true,
            }}
            index={0}
            pairs={[]}
            {theme}
            {environmentVariables}
            onUpdateEnvironment={() => {}}
            updateParam={() => {}}
            updateCheck={() => {}}
            deleteParam={() => {}}
            isInputBoxEditable={false}
            isCheckBoxEditable={false}
            {dynamicExpression}
            {handleOpenCurrentDynamicExpression}
          />
        {/if}

        <!-- Showing Duplicate Fake Rows For Diff/Merge View -->
        {#if !isMergeViewLoading && showMergeView && hasChanges}
          {#each diffPairs as element, index (index)}
            <LazyElement
              element={{
                key: element.key,
                value: element.value,
                checked: element.checked,
              }}
              {index}
              pairs={diffPairs}
              {theme}
              {environmentVariables}
              {onUpdateEnvironment}
              {updateParam}
              {updateCheck}
              {deleteParam}
              isInputBoxEditable={false}
              isCheckBoxEditable={true}
              customClass={`diff-row diff-${element.diffType}`}
              {dynamicExpression}
              {handleOpenCurrentDynamicExpression}
            />
            <!-- isInputBoxEditable={element.diffType !== "deleted"} -->
            <!-- isCheckBoxEditable={element.diffType !== "deleted"} -->

            <!-- Add Accept/Reject buttons for each changed row -->
            {#if element.diffType === "added" || element.diffType === "deleted"}
              <div class="diff-actions">
                <button
                  class="diff-action-btn accept"
                  on:click|stopPropagation={() => acceptChange(index)}
                >
                  <CheckMarkIcon color="white" size="16px" />
                </button>
                <button
                  class="diff-action-btn reject"
                  on:click|stopPropagation={() => rejectChange(index)}
                >
                  <ArrowUndoRegular color="white" size="16px" />
                </button>
              </div>
            {/if}
          {/each}

          <div
            class="d-flex justify-content-end mt-3 me-1 gap-2 merge-view-act-btns"
          >
            <Button
              title={"Keep the Changes"}
              size={"small"}
              type={"primary"}
              onClick={applyChanges}
            ></Button>
            <Button
              title={"Undo"}
              size={"small"}
              type={"secondary"}
              onClick={undoChanges}
            ></Button>

            <!-- MergeView Navigation controls - Old -->
            <div class="merge-view-navigation">
              <div class="merge-navigation-counter-wrapper">
                <div class="merge-navigation-controls">
                  <span class="merge-nav-counter">
                    {totalChanges === 0
                      ? "0 of 0"
                      : `${currentChangeIndex + 1} of ${totalChanges}`}
                  </span>

                  <button
                    class="merge-nav-button"
                    on:click={goToPreviousChange}
                    disabled={totalChanges === 0}
                    title="Previous change (Alt+Up)"
                  >
                    <ArrowUpFilled
                      size={"16px"}
                      color={"var(--bg-ds-neutral-100)"}
                    />
                  </button>

                  <button
                    class="merge-nav-button"
                    on:click={goToNextChange}
                    disabled={totalChanges === 0}
                    title="Next change (Alt+Down)"
                  >
                    <ArrowDownRegular
                      size={"16px"}
                      color={"var(--bg-ds-neutral-100)"}
                    />
                  </button>
                </div>
              </div>
            </div>
          </div>
        {:else}
          {#each pairs as element, index (index)}
            <LazyElement
              {element}
              {index}
              {pairs}
              {theme}
              {environmentVariables}
              {onUpdateEnvironment}
              {updateParam}
              {updateCheck}
              {deleteParam}
              {isInputBoxEditable}
              {isCheckBoxEditable}
              {dynamicExpression}
              {handleOpenCurrentDynamicExpression}
            />
          {/each}
        {/if}
      </div>
    </section>
  {:else}
    <!-- Bulk Edit section Start -->
    <section>
      <div class="d-flex flex-column w-100" style="font-size:12px;">
        <!-- Bulk Edit Heading -->
        <div
          class="px-3 d-flex align-items-center"
          style="justify-content: space-between; background-color: var(--bg-ds-surface-400);border-radius: 2px;padding:1px 0px;"
        >
          <!-- Bulk Edit Text  -->
          <div class="d-flex align-items-center">
            <p
              class="mb-0 text-fs-12 fw-medium"
              style="color:var(--text-ds-neutral-200)"
            >
              Bulk Edit
            </p>

            <div>
              {#if isBulkEditHeaderInfoRequired}
                <div
                  class="d-flex align-items-center rounded-1 justify-content-center position-relative"
                  style="height: 18px; width:18px; "
                >
                  <div
                    on:mouseenter={handleAutoGeneratedInfoHover}
                    on:mouseleave={handleAutoGeneratedInfoHover}
                    style="cursor: pointer; margin-bottom:2px"
                  >
                    <Tooltip
                      size="medium"
                      title="Auto-Generated Headers"
                      subtext="Auto-generated headers cannot be updated in Bulk Edit
                          mode. In order to manage auto-generated headers,
                          switch back to the Key-Value edit view."
                      placement="bottom-center"
                    >
                      <Information
                        height={"12px"}
                        width={"12px"}
                        color={"var(--bg-secondary-950)"}
                      />
                    </Tooltip>
                  </div>
                </div>
              {/if}
            </div>
          </div>

          <!-- Bulk Edit Button -->
          {#if bulkEditPlaceholder}
            <div class="pe-0 d-flex align-items-center gap-1">
              {#if !isValidSyntax}
                <div
                  class="d-flex align-items-center justify-content-center position-relative border-radius-3 me-1"
                  style="height: 18px; width:18px; z-index:1; "
                >
                  <div
                    on:mouseenter={handleErrorHover}
                    on:mouseleave={handleErrorHover}
                    style="cursor: pointer;"
                  >
                    <Tooltip
                      size="medium"
                      title="Status Error"
                      subtext="Please verify the syntax for keys and values, & ensure you follow the correct format when adding them. For example: userId:12345."
                      placement="left-top"
                    >
                      <ErrorInfoIcon
                        height={"12px"}
                        width={"12px"}
                        color={"var(--dangerColor)"}
                      />
                    </Tooltip>
                  </div>
                </div>
              {/if}
              <div style="margin-right: 2px;">
                <Toggle
                  bind:isActive={bulkToggle}
                  label="Bulk Edit"
                  fontSize="12px"
                  fontWeight="400"
                  onClick={handleBulkTextUpdate}
                  textColor="var(--text-ds-neutral-200)"
                  onChange={toggleBulkEdit}
                />
              </div>
            </div>
          {/if}
        </div>

        <!-- Bulk Edit TextArea starts -->
        <div style="height:100%">
          {#if isBulkEditLoaded}
            <BulkEditEditor
              bind:value={bulkText}
              on:change={handleBulkTextarea}
              {enableKeyValueHighlighting}
              class={`sparrow-fs-18 me-0 outline-none`}
              placeholder={bulkEditPlaceholder}
              bind:isMergeViewLoading
              bind:isMergeViewEnabled={showMergeView}
              bind:newModifiedContent={diffBulkText}
              handleOpenDE={handleOpenCurrentDynamicExpression}
            />
          {/if}
        </div>
        <!-- Bulk Edit TextArea end -->
      </div>
    </section>
  {/if}
</div>

<style>
  .pair-header-row {
    /* border-top: 0.5px solid var(--border-secondary-315); */
    padding-top: 3px;
    padding-bottom: 3px;
    background-color: var(--bg-ds-surface-400);
    height: 28px;
  }
  .header-text {
    color: var(--text-ds-neutral-200);
    font-family: "Inter", sans-serif;
    font-weight: 500;
    font-size: 12px;
  }

  .merge-view-label {
    font-size: 12px;
    color: var(--text-ds-neutral-200);
    font-weight: 400;
    display: flex;
    align-items: center;
  }

  .merge-view-act-btns {
    position: sticky;
    bottom: 10px;
  }

  .diff-actions {
    position: absolute;
    right: 12px;
    transform: translateY(-103%);
    /* display: flex; */
    display: none;
    /* gap: 4px; */
    align-items: center;
    background-color: var(--bg-ds-primary-400);
  }

  .diff-action-btn {
    width: 26px;
    height: 26px;
    border: none;
    background-color: transparent;
  }
  .diff-action-btn:hover {
    background-color: var(--bg-ds-primary-500);
  }

  /* Diff/Merge View: Style for new row added */
  :global(.diff-row.diff-added) {
    /* background-color: #113b21 !important ; */
    background-color: var(--bg-ds-success-800) !important ;
  }

  /* Diff/Merge View: Style for row modified */
  :global(.diff-row.diff-modified) {
    /* background-color: #113b21 !important ; */
    background-color: var(--bg-ds-success-800) !important ;
  }

  /* Diff/Merge View: Style for new row deleted */
  :global(.diff-row.diff-deleted) {
    /* background-color: #3d1514 !important; */
    background-color: var(--bg-ds-danger-800) !important;
  }

  .merge-view-act-btns {
    position: sticky;
    bottom: 4px;
  }

  :global(.highlighted) {
    border: 1px solid goldenrod !important;
  }

  /* Merge View Navigation Styles */
  .merge-view-navigation {
    display: inline-flex;
    align-items: center;
    /* margin-right: 12px; */
  }

  .merge-navigation-counter-wrapper {
    display: flex;
    align-items: center;
  }

  .merge-navigation-controls {
    display: flex;
    align-items: center;
    height: 28px;
    border: 1px solid var(--bg-ds-surface-400);
    border-radius: 4px;
    background-color: var(--bg-ds-surface-400);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  }

  .merge-nav-button {
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: none;
    cursor: pointer;
    padding: 0;
    width: 24px;
    height: 100%;
    color: var(--bg-ds-surface-400);
    border-radius: 4px;
    transition: background-color 0.2s;
  }

  .merge-nav-button:hover:not(:disabled) {
    background-color: var(--bg-ds-surface-200);
  }

  .merge-nav-button:active:not(:disabled) {
    background-color: var(--bg-ds-surface-200);
  }

  /* .merge-nav-button:disabled {
    color: #9ca3af;
    cursor: not-allowed;
  } */

  .merge-nav-counter {
    /* padding: 0 10px; */
    font-size: 0.75rem;
    font-weight: 500;
    color: white;
    min-width: 60px;
    text-align: center;
    user-select: none;
  }
</style>
